home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / actlib13.zip / STRINGS.ZIP / STRCALC.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  5KB  |  213 lines

  1. /*  Copyright (C) 1993   Marc Stern  (internet: stern@mble.philips.be)  */
  2.  
  3. #include "strings.h"
  4. #include <math.h>
  5. #include <ctype.h>
  6. #include <stdio.h>
  7.  
  8.  
  9. /*
  10.    Functions :   get_expr
  11.                  fetch_operand
  12.                  simplify
  13.                  strcalc
  14.  
  15. */
  16.  
  17. static char *string;
  18. static long double near get_expr( void );
  19. static long double near fetch_operand( void );
  20.  
  21.  
  22.  
  23. static char * near simplify( char *number )
  24.  
  25. { char point = 0;
  26.   char *ptr1 , *ptr2;
  27.  
  28.   for ( ptr1 = ptr2 = number; *ptr1; ptr1 ++ )
  29.     {
  30.      if ( *ptr1 != '0' ) ptr2 = ptr1;
  31.      if ( *ptr1 == '.' ) point = 1;
  32.     }
  33.  
  34.   if ( point ) *(ptr2 + 1) = '\0';
  35.   if ( *ptr2 == '.' ) *ptr2 = '\0';
  36.  
  37.   return number;
  38. }
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46. /*******************************************************
  47.  *
  48.  * Function     : get_expr
  49.  * Topic        : evaluate a mathematical expression
  50.  * Return       : value of the expression or HUGE_VAL
  51.  * Input        : string pointer (static variable)
  52.  * Side-effects : string will begin after expression
  53.  *
  54.  *******************************************************
  55.  */
  56.  
  57. long double near get_expr( void )
  58. {
  59.   long double operand1 , operand2 , result = 0;
  60.   char  operator1 = '+' , operator2;
  61.  
  62.   for ( ; *string; string++ )
  63.     {
  64.      operand1 = fetch_operand();
  65.      if ( operand1 == HUGE_VAL ) return HUGE_VAL;
  66.  
  67.      operator2 = *string;
  68.      while ( (*string == '*') || (*string == '/') || (*string == '%') || (*string == '<') || (*string == '>') || (*string == '=') )
  69.        {
  70.         string++;
  71.  
  72.     if ( *string == '=' )
  73.           switch( operator2 )
  74.         {
  75.          case '>' : operator2 = '≥'; string++; break;
  76.          case '<' : operator2 = '≤'; string++; break;
  77.          case '=' : operator2 = '='; string++; break;
  78.         }
  79.  
  80.     if ( (operator2 == '<') && (*string == '>') )
  81.           {
  82.            operator2 = '≡';
  83.            string++;
  84.           }
  85.  
  86.     operand2 = fetch_operand();
  87.     if ( operand2 == HUGE_VAL ) return HUGE_VAL;
  88.  
  89.          switch( operator2 )
  90.            {
  91.             case '*' : operand1 *= operand2; break;
  92.             case '/' : operand1 /= operand2; break;
  93.             case '%' : operand1 = (long double) ( (int) operand1 % (int) operand2 ); break;
  94.             case '=' : operand1 = (operand1 == operand2); break;
  95.             case '>' : operand1 = (operand1 > operand2); break;
  96.             case '≥' : operand1 = (operand1 >= operand2); break;
  97.             case '<' : operand1 = (operand1 < operand2); break;
  98.             case '≤' : operand1 = (operand1 <= operand2); break;
  99.             case '≡' : operand1 = (operand1 != operand2); break;
  100.            }
  101.  
  102.          operator2 = *string;
  103.        }
  104.  
  105.      if ( operator1 == '+' ) result += operand1;
  106.                         else result -= operand1;
  107.  
  108.      if ( (! *string) || (operator2 == ')') ) break;
  109.      operator1 = operator2;
  110.     }
  111.  
  112.   return result;
  113. }
  114.  
  115.  
  116.  
  117. /*******************************************************
  118.  *
  119.  * Function     : fetch_operand
  120.  * Topic        : fetch one operand or (...)
  121.  * Return       : value of the operand or (...)
  122.  * Input        : string pointer (static variable)
  123.  * Side-effects : string will begin after expression
  124.  *
  125.  *******************************************************
  126.  */
  127.  
  128. long double near fetch_operand( void )
  129. {
  130.   long double result;
  131.   char op_str[255] , *operand;
  132.  
  133.   if ( *string == '(' ) 
  134.     {
  135.      string++;
  136.      result = get_expr();
  137.      if ( (result == HUGE_VAL) || (*string != ')') ) return HUGE_VAL;  /* ) missing */
  138.      string++;
  139.     }
  140.   else
  141.     {
  142.      operand = op_str;
  143.      if ( *string == '-' ) *operand++ = *string++;
  144.  
  145.      while ( *string && (isdigit(*string) || (*string == '.')) )
  146.        *operand++ = *string++;
  147.  
  148.      *operand = '\0';
  149.      if ( sscanf(op_str , "%Lf" , &result) != 1 ) return HUGE_VAL;  /*  empty value or too large  */
  150.     }
  151.  
  152.   switch( *string )
  153.     {
  154.      case '\0':
  155.      case ')' :
  156.      case '+' :
  157.      case '-' :
  158.      case '*' :
  159.      case '/' :
  160.      case '%' :
  161.      case '<' :
  162.      case '>' :
  163.      case '=' : break;
  164.  
  165.      default  : return HUGE_VAL;   /*  Bad operator  */
  166.     }          
  167.  
  168.   return result;
  169. }
  170.  
  171.  
  172.  
  173. /***
  174.  *  Function    :  strcalc
  175.  *
  176.  *  Description :  Mathematical expression evaluation 
  177.  *
  178.  *  Parameters  :  in/out   char *   calcul      expression to calculate
  179.  *
  180.  *  Values      :  Allowed operators : + - * / () = < > <= >= <>  on floats
  181.  *                                                             %  on ints
  182.  *
  183.  *  Return      :  result   if OK
  184.  *                 HUGE_VAL if error
  185.  *
  186.  *  OS/Compiler :  All
  187.  ***/
  188.                    
  189.                 
  190. long double strcalc( char *calcul )
  191.   long double result;
  192.   char *ptr1 , *ptr2;
  193.  
  194.   for ( ptr1 = ptr2 = calcul; *ptr1; *ptr1++ = *ptr2++ )
  195.     while ( *ptr2== ' ' || *ptr2== '\t' ) ptr2++;
  196.  
  197.   *ptr2 = '\0';
  198.  
  199.   string = calcul;
  200.  
  201.   result = get_expr();
  202.  
  203.   if ( result == HUGE_VAL ) *calcul = '\0';
  204.   else {
  205.         /*  suppress trailing '0' (and final '.')  */
  206.            sprintf( calcul , "%Lf" , result );
  207.     simplify( calcul );
  208.        }       
  209.  
  210.   return result;
  211. }
  212.